package com.chenlehao.service.impl;

import com.chenlehao.aop.MyLog;
import com.chenlehao.mapper.userMapper;
import com.chenlehao.pojo.pageBean;
import com.chenlehao.pojo.user;
import com.chenlehao.service.userService;
import com.chenlehao.utils.jwt;
import com.chenlehao.utils.uploadFile;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class userServiceImpl implements userService {
    // 注入操作数据库mapper
    @Autowired
    public userMapper userMapper;
    @Autowired
    // 注入上传文件工具类
    public uploadFile uploadFile;

    @Autowired
    public jwt jwt;

    @Override
    @MyLog
    public pageBean pageList(int page, int pageSize) {
        PageHelper.startPage(page, pageSize);
        List<user> list = userMapper.list();
        Page<user> paged = (Page<user>) list;
        return new pageBean((int) paged.getTotal(), paged.getResult());
    }

    @Override
    public void upload(MultipartFile image) throws IOException {
        log.info("上传文件{}", image);
        // 获取唯一文件名
        // 使用uuid字符串
        String uuid = UUID.randomUUID().toString();
        // 新文件名为uuid加上原来的文件名
        String newFileName = uuid + image.getOriginalFilename();
        // 将文件存储到服务器磁盘路径
        image.transferTo(new File("C:\\Users\\Administrator\\Desktop\\java\\mybatis\\src\\main\\java\\com\\chenlehao\\static\\" + newFileName));
    }

    @Override
    public String uploadOSS(MultipartFile file) throws IOException {
        String url = uploadFile.upload(file);
        return url;
    }

    @Override
    public String login(String username) {
        user user = judge(username);
        if (user == null) {
            return "";
        } else {
            String jwt1 = jwt.getJwt(user.getId(), user.getName());
            return jwt1;
        }
    }

    // 判断用户名(密码)是否正确
    @Override
    public user judge(String username) {
        // 查询用户
        List<user> list = userMapper.selectName(username);
        log.info("查询用户名结果", list.toString());
        if (list.size() == 0) {
            return null;
        } else {
            return list.get(0);
        }
    }

    @Transactional(rollbackFor = Exception.class) // 事务注释
    @Override
    public void test() throws Exception {
        try {
            // 事务的作用是可以把一整个方法判为一个整体
            // 只要方法中有一个点报错了, 则之前的所有操作(数据库增删改)都会进行一个回滚操作
            // 比如要删除一个部门, 而部门会链接到部门下的人员表, 要同时删除部门下的所有人员,如果删除了部门,而正好报错导致删除人员失败,就会出现逻辑不对
            // 这个时候就可以使用事务, 一旦报错, 删除部门也会回滚回来, 就不会出现逻辑错误
            userMapper.del(109);
            log.info("报错");
            // 报错点, 事务回滚识别报错默认只会识别运行报错, 而如果是自己抛出的错误, 并不会回滚
            // 需要在注释上加入 rollbackFor = Exception.class 用于控制出现何种错误时, 事务回滚
//        int a = 1/0; // 执行错误 RuntimeException
//            if (true) {
//                throw new Exception("报错了");
//            }

            // 再一个事务中调用方法
            userMapper.del(110);
        } finally {
            innerTest();
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerTest() {
        // 在一个事务方法内调用另一个事务修饰的方法, 这个方法会默认加到父方法的事务上, 这就是事务的传播, 但如果此时我不想被父方法的影响
        // 要新开一个事务, 也就是当父方法报错, 子方法并不会受到影响, 不会回滚, 则需要修饰符加 Propagation
        /*
            1. Propagation.REQUIRED: 大部分情况下都是用该传播行为即可。
            2. Propagation.REQUIRES_NEW: 当我们不希望事务之间相互影响时，可以使用该传播行为。
               比如:下订单前需要记录日志，不论订单保存成功与否，都需要保证日志记录能够记录成功。
         */
        user user = new user();
        user.setName("陈");
        user.setAge(30);
        user.setSex(0);
        user.setHobby("学习");
        userMapper.insert(user);
        log.info("删除108");
    }
}
